/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package org.openbookformat.obffinder;

import java.io.IOException;
import java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
import javax.swing.JOptionPane;
import javax.swing.text.BadLocationException;
import org.openbookformat.obffinder.filters.Filter;
import org.openbookformat.obffinder.filters.ReplaceFilter;
import org.openide.cookies.EditorCookie;
import org.openide.text.DataEditorSupport;
import org.openide.util.Exceptions;

/**
 *
 * @author MUFEED
 */
public class FindUtil {
    private String findText;
    private String replaceText;
    private boolean regExp;
    private boolean ignoreCase;
    private boolean useVariables;
    private boolean useIgonreNewLine;
    private Filter filter;

    public FindUtil(String find_text, String replace_text) {
        this.findText = find_text;
        this.replaceText = replace_text;
    }

    public ArrayList<FindResult> find(EditorCookie ed) {
        return find(ed, 0);
    }
    
    public ArrayList<FindResult> find(EditorCookie ed, int start) {
        String text = null;
        try {
            
            text = ed.openDocument().getText(start, ed.openDocument().getLength());
        } catch (IOException ex) {
            //Waiting for netbeans to fix this 
            //System.out.println(ex.getMessage());
            Exceptions.printStackTrace(ex);
        } catch (BadLocationException ex) {
            Exceptions.printStackTrace(ex);
        }

        ArrayList<FindResult> r = new ArrayList<FindResult>();        
        if(ed == null || text == null)
            return new ArrayList<FindResult>();
        try {
            if(regExp) {

                int flags = (ignoreCase?Pattern.CASE_INSENSITIVE:0)
                        | (useIgonreNewLine?Pattern.DOTALL:0);
                Pattern pattern = Pattern.compile(findText, flags);
                Matcher matcher = pattern.matcher(text);
                String found = null;
                while (matcher.find()) {
                    found = matcher.group();
                    r.add(new FindResult(ed, matcher.start(), true, found,
                            useVariables? pattern.matcher(found).
                            replaceAll(replaceText):replaceText));
                    if(useVariables)
                        assignVariables(r.get(r.size() - 1), findText);
                }
            } else {
                //normal find
                int idx = -1;
                idx = text.indexOf(findText);
                while (idx != -1) {
                    if (idx != -1) {
                        r.add(new FindResult(ed, idx, true, findText, replaceText));
                    }
                    idx += findText.length();
                    idx = text.indexOf(findText, idx <= text.length()?idx:
                        text.length());
                }
            }
        } catch (PatternSyntaxException pse) {
            JOptionPane.showMessageDialog(null, pse.getMessage());
        }
        if(filter != null && filter instanceof ReplaceFilter) {
            for(int i = 0; i < r.size(); i++) {
                r.get(i).setReplace(((ReplaceFilter) filter).process(r.get(i).getFind()));
            }
        }
        
        for(int i = 0; i < r.size(); i++) {
            if(r.get(i).getFind().equals(r.get(i).getReplace())) 
                r.remove(i--);
        }
        
        return r;
    }


    public String getFindText() {
        return findText;
    }

    public void setFindText(String findText) {
        this.findText = findText;
    }

    public boolean isIgnoreCase() {
        return ignoreCase;
    }

    public void setIgnoreCase(boolean ignoreCase) {
        this.ignoreCase = ignoreCase;
    }

    public boolean isRegExp() {
        return regExp;
    }

    public void setRegExp(boolean regExp) {
        this.regExp = regExp;
    }

    public String getReplaceText() {
        return replaceText;
    }

    public void setReplaceText(String replaceText) {
        this.replaceText = replaceText;
    }

    public boolean isUseIgonreNewLine() {
        return useIgonreNewLine;
    }

    public void setUseIgonreNewLine(boolean useIgonreNewLine) {
        this.useIgonreNewLine = useIgonreNewLine;
    }

    public boolean isUseVariables() {
        return useVariables;
    }

    public void setUseVariables(boolean useVariables) {
        this.useVariables = useVariables;
    }

    public Filter getFilter() {
        return filter;
    }

    public void setFilter(Filter filter) {
        this.filter = filter;
    }

    private void assignVariables(FindResult r, String findText) {
        //find number of varialbes
        int count = 0;
        for(int i = 0; i < findText.length(); i++)
            if(findText.charAt(i) == '(')
                count++;
        
        Pattern pattern = Pattern.compile(findText);
        for (int i = 0; i < count; i++) {
            try {
                System.out.println("r.getFind():" + r.getFind());
                System.out.println("replaceAll:" + "$" + (i + 1));
                System.out.println("Adding:" + pattern.matcher(r.getFind()).replaceAll("$" + (i + 1)));
                r.addVariable(pattern.matcher(r.getFind()).replaceAll("$" + (i + 1)));
            } catch (IndexOutOfBoundsException IE) {
                //counting done; do nothing
                IE.printStackTrace();
                break;
            }
        }
    }
    
}
